﻿using System;
using System.Data;
using System.Data.Common;
using System.Security;
using System.Security.Permissions;
using Codemonk.Common.ObjectModel;
namespace Codemonk.Common.Data
{
    public class DbAccessor : IDbAccessor
    {
        public DbAccessor() { }

        protected readonly object Sync = new object();

        protected bool disposed = false;

        #region IDisposable

        ~DbAccessor()
        {
            Dispose(false);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (disposed) return;
            if (disposing)
            {
                lock (Sync)
                {
                    Close();
                    this.p_ConnectionPool.Dispose();
                }
            }
            disposed = true;
        }

        public virtual void Dispose()
        {
            Dispose(true);
            System.GC.SuppressFinalize(this);
        }

        #endregion

        #region IDbAccessor 成员

        protected DbProviderFactory p_Factory;
        public virtual DbProviderFactory ProviderFactory
        {
            get
            {
                if (p_Factory == null)
                {
                    lock (Sync)
                    {
                        if (p_Factory == null)
                        {
                            p_Factory = DbProviderFactories.GetFactory(ProviderInvariantName);
                        }
                    }
                }
                return p_Factory;
            }
            set
            {
                p_Factory = value;
            }
        }

        public virtual string ConnectionString
        {
            get;
            set;
        }

        public virtual string ProviderInvariantName { get; set; }

        public virtual DbDataSourceEnumerator CreateDataSourceEnumerator()
        {
            return ProviderFactory.CreateDataSourceEnumerator();
        }

        public virtual CodeAccessPermission CreatePermission(PermissionState state)
        {
            return ProviderFactory.CreatePermission(state);
        }
        #endregion

        #region IDbConnectionCreater 成员

        protected ConnectionPool<IDbConnection> p_ConnectionPool;
        /// <summary>
        /// 内部连接池
        /// </summary>
        protected virtual ConnectionPool<IDbConnection> ConnectionPool
        {
            get
            {
                if (p_ConnectionPool == null)
                {
                    lock (Sync)
                    {
                        if (p_ConnectionPool == null)
                        {
                            p_ConnectionPool = new ConnectionPool<IDbConnection>(() => ProviderFactory.CreateConnection(), 128);
                            p_ConnectionPool.Predicate = c => c.State != ConnectionState.Open;
                        }
                    }
                }
                return p_ConnectionPool;
            }
        }

        public virtual IDbConnection DefaultConnection
        {
            get
            {
                if (disposed)
                    throw new ObjectDisposedException("对象已经释放");
                if (string.IsNullOrEmpty(ConnectionString))
                    return null;
                var conn = CreateConnection();
                if (string.IsNullOrEmpty(conn.ConnectionString))
                    conn.ConnectionString = ConnectionString;
                if (AutoOpen)
                {
                    Open(conn);
                }
                return conn;
            }
        }

        public virtual DbConnectionStringBuilder CreateConnectionStringBuilder()
        {
            return ProviderFactory.CreateConnectionStringBuilder();
        }

        protected bool p_AutoOpen = true;

        public virtual bool AutoOpen
        {
            get
            {
                return p_AutoOpen;
            }
            set
            {
                p_AutoOpen = value;
            }
        }

        public virtual void Open(IDbConnection connection = null)
        {
            if (connection == null)
                connection = DefaultConnection;
            if (connection.State == ConnectionState.Closed)
            {
                connection.Open();
            }
            else if (connection.State == ConnectionState.Broken)
            {
                connection.Close();
                connection.Open();
            }
            //else if (connection.State == ConnectionState.Open)
            //{
            //    connection.Close();
            //    connection.Open();
            //}
        }

        public virtual void Close(IDbConnection connection = null)
        {
            if (connection == null)
                connection = DefaultConnection;
            if (connection.State == ConnectionState.Open)
            {
                connection.Close();
            }
            else if (connection.State == ConnectionState.Broken)
            {
                connection.Close();
            }
            else if (connection.State == ConnectionState.Connecting)
            {
                connection.Close();
            }
        }

        public virtual IDbConnection CreateConnection()
        {
            return ConnectionPool.Borrow();
        }

        public virtual IDbConnection CreateConnection(string connectionString)
        {
            var conn = CreateConnection();
            conn.ConnectionString = ConnectionString;
            return conn;
        }

        public virtual IDbTransaction BeginTransaction()
        {
            return BeginTransaction(DefaultConnection);
        }

        public virtual IDbTransaction BeginTransaction(IsolationLevel iso)
        {
            return BeginTransaction(DefaultConnection, iso);
        }

        public virtual IDbTransaction BeginTransaction(IDbConnection connection)
        {
            if (connection == null)
                throw new NullReferenceException("参数connection为空");
            return connection.BeginTransaction();
        }

        public virtual IDbTransaction BeginTransaction(IDbConnection connection, IsolationLevel iso)
        {
            if (connection == null)
                throw new NullReferenceException("参数connection为空");
            return connection.BeginTransaction(iso);
        }

        #endregion

        #region IDbCommandCreater 成员

        public virtual DbCommandBuilder CreateCommandBuilder()
        {
            return ProviderFactory.CreateCommandBuilder();
        }

        public virtual IDbCommand CreateCommand()
        {
            return ProviderFactory.CreateCommand();
        }

        public virtual IDbCommand CreateCommand(IDbConnection connection, string cmdtext, params IDataParameter[] paras)
        {
            return CreateCommand(connection, cmdtext, CommandType.Text, null, paras);
        }

        public virtual IDbCommand CreateCommand(IDbConnection connection, string cmdtext, DbParameterBuilder builder)
        {
            if (builder == null)
                return CreateCommand(connection, cmdtext, CommandType.Text);
            return CreateCommand(connection, cmdtext, CommandType.Text, null, builder.ToArray());
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2100:检查 SQL 查询是否存在安全漏洞")]
        public virtual IDbCommand CreateCommand(IDbConnection connection, string cmdtext, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null, params IDataParameter[] paras)
        {
            if (connection == null)
                throw new NullReferenceException("参数connection为空");
            if (string.IsNullOrEmpty(cmdtext))
                throw new NullReferenceException("参数cmdtext为空");
            var cmd = CreateCommand();
            cmd.Connection = connection;
            cmd.CommandText = cmdtext;
            cmd.CommandType = cmdtype;
            if (tran != null)
            {
                cmd.Transaction = tran;
            }
            if (paras != null && paras.Length > 0)
            {
                foreach (var para in paras)
                {
                    cmd.Parameters.Add(para);
                }
            }
            return cmd;
        }

        public virtual IDbCommand CreateCommand(IDbConnection connection, string cmdtext, DbParameterBuilder builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null)
        {
            if (builder == null)
                return CreateCommand(connection, cmdtext, cmdtype, tran);
            return CreateCommand(connection, cmdtext, cmdtype, tran, builder.ToArray());
        }

        public virtual IDbCommand CreateCommand(string cmdtext, params IDataParameter[] paras)
        {
            return CreateCommand(DefaultConnection, cmdtext, CommandType.Text, null, paras);
        }

        public virtual IDbCommand CreateCommand(string cmdtext, DbParameterBuilder builder)
        {
            return CreateCommand(DefaultConnection, cmdtext, builder);
        }

        public virtual IDbCommand CreateCommand(string cmdtext, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null, params IDataParameter[] paras)
        {
            return CreateCommand(DefaultConnection, cmdtext, CommandType.Text, null, paras);
        }

        public virtual IDbCommand CreateCommand(string cmdtext, DbParameterBuilder builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null)
        {
            return CreateCommand(DefaultConnection, cmdtext, builder);
        }

        public virtual IDbCommand CreateCommand<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            return CreateCommand(connection, cmdtext, builder.ToArray());
        }

        public virtual IDbCommand CreateCommand<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null) where T : IDataParameter, new()
        {
            if (builder == null)
                return CreateCommand(connection, cmdtext, cmdtype, tran);
            return CreateCommand(connection, cmdtext, cmdtype, tran, builder.ToArray());
        }

        public virtual IDbCommand CreateCommand<T>(string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            return CreateCommand(DefaultConnection, cmdtext, builder);
        }

        public virtual IDbCommand CreateCommand<T>(string cmdtext, DbParameterBuilder<T> builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null) where T : IDataParameter, new()
        {
            return CreateCommand(DefaultConnection, cmdtext, builder, cmdtype, tran);
        }

        #endregion

        #region IExecuteNonQueryable 成员

        public virtual int ExecuteNonQuery(IDbCommand cmd, IDbTransaction tran = null)
        {
            if (cmd == null)
                throw new NullReferenceException("参数cmd为空");
            if (tran != null)
                cmd.Transaction = tran;
            return cmd.ExecuteNonQuery();
        }

        public virtual int ExecuteNonQuery(string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, paras))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery(string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery(string cmdtext, IDbTransaction tran = null, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, paras))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        public virtual int ExecuteNonQuery(string cmdtext, DbParameterBuilder builder, IDbTransaction tran = null)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        public virtual int ExecuteNonQuery(string cmdtext, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, cmdtype, tran, paras))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        public virtual int ExecuteNonQuery(string cmdtext, DbParameterBuilder builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder, cmdtype, tran))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        public virtual int ExecuteNonQuery(IDbConnection connection, string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(connection, cmdtext, paras))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery(IDbConnection connection, string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery(IDbConnection connection, string cmdtext, IDbTransaction tran = null, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, CommandType.Text, tran, paras))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery(IDbConnection connection, string cmdtext, DbParameterBuilder builder, IDbTransaction tran = null)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder, CommandType.Text, tran))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery(IDbConnection connection, string cmdtext, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, cmdtype, tran, paras))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery(IDbConnection connection, string cmdtext, DbParameterBuilder builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder, cmdtype, tran))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery<T>(string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery<T>(string cmdtext, DbParameterBuilder<T> builder, IDbTransaction tran = null) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        public virtual int ExecuteNonQuery<T>(string cmdtext, DbParameterBuilder<T> builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder, cmdtype))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        public virtual int ExecuteNonQuery<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd);
            }
        }

        public virtual int ExecuteNonQuery<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder, IDbTransaction tran = null) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        public virtual int ExecuteNonQuery<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder, CommandType cmdtype = CommandType.Text, IDbTransaction tran = null) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return ExecuteNonQuery(cmd, tran);
            }
        }

        #endregion

        #region IExecuteScalarQueryable 成员

        public virtual object ExecuteScalar(IDbCommand cmd)
        {
            if (cmd == null)
                throw new NullReferenceException("参数cmd为空");
            return cmd.ExecuteScalar();
        }

        public virtual object ExecuteScalar(IDbConnection connetion, string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(connetion, cmdtext, paras))
            {
                return ExecuteScalar(cmd);
            }
        }

        public virtual object ExecuteScalar(IDbConnection connetion, string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(connetion, cmdtext, builder))
            {
                return ExecuteScalar(cmd);
            }
        }

        public virtual object ExecuteScalar(string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, paras))
            {
                return ExecuteScalar(cmd);
            }
        }

        public virtual object ExecuteScalar(string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteScalar(cmd);
            }
        }

        protected Type p_IConvertible = typeof(IConvertible);

        public virtual R ExecuteScalar<R>(IDbCommand cmd)
        {
            var obj = ExecuteScalar(cmd);
            if (obj == null) return default(R);
            if (obj is string || obj is char)
                return (R)obj;
            else if (p_IConvertible.IsInstanceOfType(obj))
            {
                var ret = ((IConvertible)obj).ToType(typeof(R), null);
                if (ret != null)
                    return (R)ret;
            }
            throw new NotSupportedException("对象类型现在不受支持");
        }

        public virtual R ExecuteScalar<R>(IDbConnection connetion, string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(connetion, cmdtext, paras))
            {
                return ExecuteScalar<R>(cmd);
            }
        }

        public virtual R ExecuteScalar<R>(IDbConnection connetion, string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(connetion, cmdtext, builder))
            {
                return ExecuteScalar<R>(cmd);
            }
        }

        public virtual R ExecuteScalar<R>(string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, paras))
            {
                return ExecuteScalar<R>(cmd);
            }
        }

        public virtual R ExecuteScalar<R>(string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteScalar<R>(cmd);
            }
        }

        public virtual object ExecuteScalar<T>(IDbConnection connetion, string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connetion, cmdtext, builder))
            {
                return ExecuteScalar(cmd);
            }
        }

        public virtual object ExecuteScalar<T>(string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteScalar(cmd);
            }
        }

        public virtual R ExecuteScalar<R, T>(IDbConnection connetion, string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connetion, cmdtext, builder))
            {
                return ExecuteScalar<R>(cmd);
            }
        }

        public virtual R ExecuteScalar<R, T>(string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteScalar<R>(cmd);
            }
        }

        #endregion

        #region IDataReaderQueryable 成员

        public virtual IDataReader ExecuteReader(IDbCommand cmd, CommandBehavior behaivor = CommandBehavior.Default)
        {
            if (cmd == null)
                throw new NullReferenceException("参数cmd为空");
            return cmd.ExecuteReader(behaivor);
        }

        public virtual IDataReader ExecuteReader(IDbConnection connetion, string cmdtext, CommandType cmdtype = CommandType.Text, CommandBehavior behaivor = CommandBehavior.Default, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(connetion, cmdtext, cmdtype, null, paras))
            {
                return ExecuteReader(cmd, behaivor);
            }
        }

        public virtual IDataReader ExecuteReader(IDbConnection connection, string cmdtext, DbParameterBuilder builder, CommandType cmdtype = CommandType.Text, CommandBehavior behaivor = CommandBehavior.Default)
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder, cmdtype))
            {
                return ExecuteReader(cmd, behaivor);
            }
        }

        public virtual IDataReader ExecuteReader(string cmdtext, CommandType cmdtype = CommandType.Text, CommandBehavior behaivor = CommandBehavior.Default, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, cmdtype, null, paras))
            {
                return ExecuteReader(cmd, behaivor);
            }
        }

        public virtual IDataReader ExecuteReader(string cmdtext, DbParameterBuilder builder, CommandType cmdtype = CommandType.Text, CommandBehavior behaivor = CommandBehavior.Default)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder, cmdtype))
            {
                return ExecuteReader(cmd, behaivor);
            }
        }

        public virtual IDataReader ExecuteReader<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder, CommandType cmdtype = CommandType.Text, CommandBehavior behaivor = CommandBehavior.Default) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder, cmdtype))
            {
                return ExecuteReader(cmd, behaivor);
            }
        }

        public virtual IDataReader ExecuteReader<T>(string cmdtext, DbParameterBuilder<T> builder, CommandType cmdtype = CommandType.Text, CommandBehavior behaivor = CommandBehavior.Default) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder, cmdtype))
            {
                return ExecuteReader(cmd, behaivor);
            }
        }

        #endregion

        #region IDbDataAdapterCreater 成员

        public IDbDataAdapter FillCommand(IDbDataAdapter adapter)
        {
            var builder = CreateCommandBuilder();
            var dapt = adapter as DbDataAdapter;
            if (dapt != null)
            {
                builder.DataAdapter = dapt;
                builder.RefreshSchema();
                builder.SetAllValues = false;
                adapter.InsertCommand = builder.GetInsertCommand();
                adapter.UpdateCommand = builder.GetUpdateCommand();
                adapter.DeleteCommand = builder.GetDeleteCommand();
                dapt.Disposed += (s, e) => builder.Dispose();
            }
            return adapter;
        }


        public virtual IDbDataAdapter CreateDataAdapter()
        {
            return ProviderFactory.CreateDataAdapter();
        }

        public virtual IDbDataAdapter CreateDataAdapter(IDbCommand cmd)
        {
            if (cmd == null)
                throw new NullReferenceException("参数cmd为空");
            if (cmd.Connection == null)
                throw new ArgumentNullException("参数cmd未设置连接");
            var adapter = CreateDataAdapter();
            adapter.SelectCommand = cmd;
            return adapter;
        }

        public virtual IDbDataAdapter CreateDataAdapter(IDbConnection connection, string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(connection, cmdtext, paras))
            {
                return CreateDataAdapter(cmd);
            }
        }

        public virtual IDbDataAdapter CreateDataAdapter(IDbConnection connection, string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return CreateDataAdapter(cmd);
            }
        }

        public virtual IDbDataAdapter CreateDataAdapter(string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, paras))
            {
                return CreateDataAdapter(cmd);
            }
        }

        public virtual IDbDataAdapter CreateDataAdapter(string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return CreateDataAdapter(cmd);
            }
        }

        public virtual IDbDataAdapter CreateDataAdapter<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return CreateDataAdapter(cmd);
            }
        }

        public virtual IDbDataAdapter CreateDataAdapter<T>(string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return CreateDataAdapter(cmd);
            }
        }

        #endregion

        #region IDataParameterCreater 成员

        //public abstract DbParameterBuilder<R> CreateParameterBuilder();

        //public abstract DbParameterBuilder<R> CreateParameterBuilder(int capacity);

        //public abstract DbParameterBuilder<R> CreateParameterBuilder(System.Collections.Generic.IEnumerable<R> source);

        public virtual DbParameterBuilder CreateParameterBuilder(bool isCheckName = false)
        {
            return new DbParameterBuilder { Factory = ProviderFactory, IsCheckParameter = isCheckName };
        }

        public virtual DbParameterBuilder CreateParameterBuilder(int capacity, bool isCheckName = false)
        {
            return new DbParameterBuilder(capacity) { Factory = ProviderFactory, IsCheckParameter = isCheckName };
        }

        public virtual IDataParameter CreateParameter()
        {
            return ProviderFactory.CreateParameter();
        }

        public virtual IDataParameter CreateParameter(string parameterName, DbType? type = null)
        {
            if (string.IsNullOrEmpty(parameterName))
                throw new NullReferenceException("参数parameterName为空");
            var ret = CreateParameter();
            ret.ParameterName = parameterName;
            if (type.HasValue)
                ret.DbType = type.Value;
            return ret;
        }

        public virtual IDataParameter CreateParameter(string parameterName, object value, DbType? type = null)
        {
            var ret = CreateParameter(parameterName, type);
            ret.Value = value;
            return ret;
        }

        public virtual IDataParameter CreateParameter(string parameterName, object value, ParameterDirection direction, bool isNullable, string sourceColumn, DbType? type = null, DataRowVersion sourceVersion = DataRowVersion.Default)
        {
            var ret = CreateParameter(parameterName, value, type);
            ret.Direction = direction;
            ret.SourceColumn = sourceColumn;
            ret.SourceVersion = sourceVersion;
            return ret;
        }

        public virtual IDataParameter[] GetFillParameters(IDbCommand cmd)
        {
            if (cmd == null)
                throw new NullReferenceException("参数cmd为空");
            var adapter = CreateDataAdapter(cmd);
            try
            {
                return GetFillParameters(adapter);
            }
            finally
            {
                var dis = adapter as IDisposable;
                if (dis != null)
                    dis.Dispose();
            }
        }

        public virtual IDataParameter[] GetFillParameters(IDbDataAdapter adapter)
        {
            if (adapter == null)
                throw new NullReferenceException("参数adapter为空");
            IDataParameter[] ret = adapter.GetFillParameters();
            return ret;
        }

        public virtual IDataParameter[] GetFillParameters(IDbConnection connection, string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(connection, cmdtext, paras))
            {
                return GetFillParameters(cmd);
            }
        }

        public virtual IDataParameter[] GetFillParameters(IDbConnection connection, string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return GetFillParameters(cmd);
            }
        }

        public virtual IDataParameter[] GetFillParameters(string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, paras))
            {
                return GetFillParameters(cmd);
            }
        }

        public virtual IDataParameter[] GetFillParameters(string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return GetFillParameters(cmd);
            }
        }

        public virtual IDataParameter[] GetFillParameters<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return GetFillParameters(cmd);
            }
        }

        public virtual IDataParameter[] GetFillParameters<T>(string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return GetFillParameters(cmd);
            }
        }

        #endregion

        #region IDataSetFillble 成员

        public virtual DataSet ExecuteSet(IDbCommand cmd)
        {
            if (cmd == null)
                throw new NullReferenceException("参数cmd为空");
            var adapter = CreateDataAdapter(cmd);
            try
            {
                return ExecuteSet(adapter);
            }
            finally
            {
                var dis = adapter as IDisposable;
                if (dis != null) dis.Dispose();
            }
        }

        public virtual DataSet ExecuteSet(IDbDataAdapter adapter)
        {
            if (adapter == null)
                throw new NullReferenceException("参数adapter为空");
            DataSet ds = new DataSet();
            adapter.Fill(ds);
            return ds;
        }

        public virtual DataSet ExecuteSet(IDbConnection connection, string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(connection, cmdtext, paras))
            {
                return ExecuteSet(cmd);
            }
        }

        public virtual DataSet ExecuteSet(IDbConnection connection, string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return ExecuteSet(cmd);
            }
        }

        public virtual DataSet ExecuteSet(string cmdtext, params IDataParameter[] paras)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, paras))
            {
                return ExecuteSet(cmd);
            }
        }

        public virtual DataSet ExecuteSet(string cmdtext, DbParameterBuilder builder)
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteSet(cmd);
            }
        }

        public virtual DataSet ExecuteSet<T>(IDbConnection connection, string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(connection, cmdtext, builder))
            {
                return ExecuteSet(cmd);
            }
        }

        public virtual DataSet ExecuteSet<T>(string cmdtext, DbParameterBuilder<T> builder) where T : IDataParameter, new()
        {
            using (var cmd = CreateCommand(DefaultConnection, cmdtext, builder))
            {
                return ExecuteSet(cmd);
            }
        }

        #endregion
    }
}
